package com.lib.core.base

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.corelibs.expand.showToast
import com.lib.core.R
import com.lib.core.api.ApiFactory
import com.lib.core.bean.BaseData
import com.lib.core.bean.ListData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketTimeoutException

private const val SUCCESS_CODE = 200


open class BaseViewModel : ViewModel() {


    protected open fun <T> getApi(clz: Class<T>): T {
        return ApiFactory.factory!!.create(clz)
    }

    val uiModel: UIModel by lazy {
        UIModel()
    }

    protected var pageIndex = 1
    protected var pageSize = 15


    fun <T> launch(
        block: suspend CoroutineScope.() -> BaseData<T>,
        success: (BaseData<T>) -> Unit,
        error: (String) -> Unit = {
            showToast(it)
        },
        isShowDialog: Boolean = false, //是否显示加载框
        isRefresh: Boolean = false,//是否是下拉刷新
    ) {
        if (isShowDialog) {
            uiModel.showDialog.postValue(true)
        }
        viewModelScope.launch {
            flow {
                emit(block())
            }   //网络请求
                .flowOn(Dispatchers.IO)  //指定网络请求的线程
                .catch { t: Throwable ->
                    run {
                        handleThrow(t)
                        if (isShowDialog) {
                            uiModel.showDialog.postValue(false)
                        }
                        //如果是下拉刷新
                        if (isRefresh) {
                            //完成刷新
                            uiModel.finishRefresh.postValue(true)
                        } else {
                            //完成加载
                            uiModel.finishLoadMore.postValue(true)
                        }
                    }
                }
                .collect {
                    handleData(it, success, error)
                    if (isShowDialog) {
                        uiModel.showDialog.postValue(false)
                    }
                    //如果是下拉刷新
                    if (isRefresh) {
                        //完成刷新
                        uiModel.finishRefresh.postValue(true)
                        checkHaveMore(it)
                    } else {
                        checkHaveMore(it)
                    }
                }
        }
    }

    open fun doRefresh(reload: Boolean) {
        if (reload) pageIndex = 1 else pageIndex++
    }


    private fun <T> checkHaveMore(baseData: BaseData<T>) {
        val data = baseData.data
        if (data is ListData<*>) {
            if (data.list.size >= pageSize) {
                //还有更多数据
                uiModel.finishLoadMore.postValue(true)
            } else {
                //没有更多数据
                uiModel.finishLoadMore.postValue(false)
            }
        }
    }

    private fun <T> handleData(
        result: BaseData<T>,
        success: (BaseData<T>) -> Unit,
        error: (String) -> Unit,
    ) {
        if (result.status == SUCCESS_CODE) {
            success(result)
        } else {
            error(result.message.ifBlank { "未知错误" })
        }
    }

    /**
     * 处理网络异常
     */
    private fun handleThrow(t: Throwable) {
        t.printStackTrace()
        when (t) {
            is ConnectException -> showToast(R.string.network_error)

            is SocketTimeoutException -> showToast(R.string.network_timeout)

            is HttpException -> showToast(R.string.network_server_error)

            else -> showToast(R.string.network_other)

        }

    }


    inner class UIModel {
        val showDialog by lazy { MutableLiveData(false) }    //显示加载框
        val finishRefresh by lazy { MutableLiveData(true) } //是否是刷新状态
        val finishLoadMore by lazy { MutableLiveData(true) } //是否是加载状态 false没有更多数据
    }
}